/*=========================================================================

Program:   Virtual Surgery
Language:  C++
Date:      2009-9-1
Version:   0.1
Mail:		   nelfylee@gmail.com

Copyright (c) 2009 Nelfy Lee. All rights reserved.

=========================================================================*/
#include "View3d.h"
#include "Source.h"


#include "vtkImageData.h"
#include "vtkPiecewiseFunction.h"
#include "vtkColorTransferFunction.h"
#include "vtkVolumeProperty.h"
#include "vtkVolumeRayCastCompositeFunction.h"
#include "vtkVolume.h"
#include "vtkRenderWindow.h"
#include "vtkRenderer.h"
#include "vtkVolumeRayCastMapper.h"
#include "vtkRendererCollection.h"
#include "vtkProperty.h"
#include "vtkInteractorStyleImage.h"
#include "vtkImageCast.h"
#include "vtkOutlineFilter.h"
#include "vtkPolyDataMapper.h"
#include "vtkContourFilter.h"
#include "vtkDataSetSurfaceFilter.h"
#include "vtkImageMarchingCubes.h"
#include "vtkSmoothPolyDataFilter.h"
#include "vtkPolyDataNormals.h"
#include "vtkSmartPointer.h"
#include "vtkInteractorStyleRubberBandPick.h"
#include "vtkRenderedAreaPicker.h"
#include "vtkExtractSelectedFrustum.h"
#include "vtkDataSetMapper.h"
#include "vtkEventQtSlotConnect.h"
#include "vtkHardwareSelector.h"
#include "vtkPlanes.h"
#include "vtkPoints.h"
#include "vtkAreaPicker.h"
#include "vtkPropPicker.h"
#include "vtkInteractorStyleTrackballCamera.h"
#include "vtkInteractorStyleTrackball.h"

#include "QVTKWidget.h"

#include <QtGui>

View3D::View3D(const QString &name, int id)
: View(name, id)
{
	m_cameraLinked=false;

	int size = style()->pixelMetric(QStyle::PM_ToolBarIconSize);
	QSize iconSize(size, size);

	m_renderer->SetBackground(82.0/255.0, 87.0/255.0, 110.0/255.0);

 	m_btnCutting = new QToolButton;
	m_btnCutting->setCheckable(true);
 	m_btnCutting->setIcon(QIcon(QPixmap(":/res/bw_cut.png")));
 	m_btnCutting->setIconSize(QSize(16, 16));
 	m_btnCutting->setAutoRaise(true);
	connect(m_btnCutting, SIGNAL(toggled(bool)), SLOT(slotCutting(bool)));

	m_layoutToolbar->addWidget(m_btnCutting);

	//m_interactorStyle = vsInteractorStyleRubberPick::New();
	m_interactorStyleTrackballCamera = vtkInteractorStyleTrackballCamera::New();
	m_qvtkWidget->GetRenderWindow()->GetInteractor()->SetInteractorStyle(m_interactorStyleTrackballCamera);

// 	m_areaPicker = vtkRenderedAreaPicker::New();
// 	m_qvtkWidget->GetRenderWindow()->GetInteractor()->SetPicker(m_areaPicker);

	initInternalObjects();


	vtkEventQtSlotConnect *Connections = vtkEventQtSlotConnect::New();
	
	Connections->Connect(m_interactorStyleTrackballCamera,vtkCommand::LeftButtonPressEvent,this,SLOT(slotLeftButtonPressed(vtkObject*, unsigned long)));
	Connections->Connect(m_interactorStyleTrackballCamera,vtkCommand::MiddleButtonReleaseEvent,this,SLOT(slotMiddleButtonReleased(vtkObject*)));
	Connections->Connect(m_interactorStyleTrackballCamera,vtkCommand::LeftButtonReleaseEvent,this,SLOT(slotLeftButtonReleased(vtkObject*, unsigned long)));
	Connections->Connect(m_interactorStyleTrackballCamera,vtkCommand::MouseMoveEvent,this,SLOT(slotMouseMove(vtkObject*)));
	Connections->Connect(m_interactorStyleTrackballCamera,vtkCommand::RightButtonReleaseEvent,this,SLOT(slotRightButtonReleased(vtkObject*)));
	Connections->Connect(m_qvtkWidget->GetRenderWindow()->GetInteractor(), vtkCommand::KeyPressEvent, 
		this, SLOT(slotProcessKeyEvent(vtkObject*,unsigned long, void*, void*)));
	Connections->Connect(m_qvtkWidget->GetRenderWindow()->GetInteractor(), vtkCommand::KeyReleaseEvent, 
		this, SLOT(slotProcessKeyEvent(vtkObject*,unsigned long, void*, void*)));
}

void 
View3D::initInternalObjects()
{
	m_isRealTimeSlicing = false;
	m_isNeedResetCamera = false;
}


void View3D::slotLeftButtonPressed(vtkObject *obj, unsigned long vtk_even)
{
	View::slotLeftButtonPressed(obj, vtk_even);
	m_lbtnPressed = true;

	int pEventPos[2];
	m_qvtkWidget->GetInteractor()->GetEventPosition(pEventPos);

	vtkPropPicker* picker = reinterpret_cast<vtkPropPicker*>(m_qvtkWidget->GetInteractor()->GetPicker());

	picker->PickProp(pEventPos[0], pEventPos[1], m_renderer);
	//if ( picker == NULL || picker->PickProp(pEventPos[0], pEventPos[1], m_renderer) == 0)
		m_interactorStyleTrackballCamera->OnLeftButtonDown();
}


void View3D::slotLeftButtonReleased(vtkObject *obj, unsigned long vtk_even)
{
	m_interactorStyleTrackballCamera->OnLeftButtonUp();

	m_lbtnPressed = false;

	if ( m_btnCutting->isChecked())
		switchMode(dmNormal);
}


void View3D::slotMouseMove(vtkObject *obj)
{
	m_interactorStyleTrackballCamera->OnMouseMove();

	if ( m_cameraLinked && m_lbtnPressed)
		emit emitLinkedCameraMoving();
}

void View3D::slotRightButtonReleased(vtkObject *obj)
{
	m_interactorStyleTrackballCamera->OnRightButtonUp();

	if ( m_btnCutting->isChecked())
	{	
		switchMode(dmPicking);
	}

// 
// 
// 	switch (m_source->getDataType())
// 	{
// 	case VTK_UNSIGNED_CHAR:
// 		removeSelectedPoints<unsigned char>();
// 		break;
// 	case VTK_FLOAT:
// 		removeSelectedPoints<float>();
// 		break;
// 	case VTK_SHORT:
// 		removeSelectedPoints<short>();
// 		break;
// 	default:
// 		return;
// 	}
}


void View3D::slotRightButtonPressed(vtkObject *obj)
{
	printf("slotRightButtonPressed\n");

	m_interactorStyleTrackballCamera->OnRightButtonDown();
}


void View3D::slotMouseEnter(vtkObject *obj)
{
}

void View3D::slotMouseLeave(vtkObject *obj)
{
}


void View3D::slotStartRealTimeSlicing()
{
	if ( m_isRealTimeSlicing)
	{
		qDebug() << "[Warning]: Other real time slicing is running";
		return;
	}

	m_isRealTimeSlicing = true;

	slotClearRealTimePropers();
}


void View3D::updateRealTimeSlicing(vtkProp *prop)
{
	static int times = 1;

	addProper(prop);

	if ( times == 1)
	{
		resetCamera();
		times = 2;
	}

	render();
	m_rtPropList.push_back(prop);
}


void View3D::slotStopRealTimeSlicing()
{
	m_isRealTimeSlicing = false;
	slotClearRealTimePropers();
}


void View3D::slotClearRealTimePropers()
{
	QList<vtkProp*>::iterator it = m_rtPropList.begin();
	for ( ; it != m_rtPropList.end(); it++)
	{
		removeProper(*it);
	}

	m_rtPropList.clear();
}


void View3D::setProperPickingMode(vtkCommand *cmd)
{
	vtkSmartPointer<vtkPropPicker> picker = vtkSmartPointer<vtkPropPicker>::New();
	m_qvtkWidget->GetInteractor()->SetPicker(picker);
	//picker->AddObserver(vtkCommand::StartPickEvent, cmd);
	picker->AddObserver(vtkCommand::PickEvent, cmd);

	//m_interactorStyle->StartSelect();
}


void View3D::switchMode(DisplayMode mode)
{
	if ( mode == dmNormal)
	{
		//m_interactorStyle->StopSelect();
	}
	else if ( mode == dmPicking)
	{
		//m_interactorStyle->StartSelect();
	}
	else if ( mode == dmProperPicking)
	{

	}

	m_displayMode = mode;
}


void View3D::slotCutting(bool checked)
{
	if ( checked)
		emit emitStartCutting();
	else
		emit emitStopCutting();
}

void View3D::slotMiddleButtonReleased(vtkObject*)
{
	m_interactorStyleTrackballCamera->OnMiddleButtonUp();

	if ( m_btnCutting->isChecked())
		emit emitDoCut();

// 	if ( !m_selectedActor)
// 		return;
// 
// 	switch (m_source->getDataType())
// 	{
// 	case VTK_UNSIGNED_CHAR:
// 		removeSelectedPoints<unsigned char>();
// 		break;
// 	case VTK_FLOAT:
// 		removeSelectedPoints<float>();
// 		break;
// 	case VTK_SHORT:
// 		removeSelectedPoints<short>();
// 		break;
// 	default:
// 		return;
// 	}
}

void View3D::slotLinkedCameraMoving()
{
	render();
}

void View3D::cameraLinked( bool flag )
{
	m_cameraLinked = flag;
}

vtkRenderWindowInteractor* View3D::interactor()
{
	return m_renderer->GetRenderWindow()->GetInteractor();
}


void View3D::slotProcessKeyEvent(vtkObject* caller,
	unsigned long eventId,
	void* clientData,
	void* callData)
{
	QKeyEvent* qe = (QKeyEvent*)callData;
	if ( !qe)
		return;

	emit emitKeyEvent(qe);
}